#include <kutils.h>
#include "memory.h"
#include "irq.h"
#include "display.h"
#include "pit.h"
#include "paging.h"
#include "task.h"

volatile u32int pit_ticks = 0;
const s32int pit_hertz = 100; //100 ticks per second means that each tick is ten milliseconds
volatile u8int pit_initalized = 0;

void pit_handler(struct regs *r);
void pit_program(s32int timer, s32int mode, s32int hz);

void pit_handler(struct regs *r)
{
	if(!r){return;}
	if(!pit_initalized){return;}

	pit_ticks++;

	//invoke the scheduler every 40 milliseconds
	if(pit_ticks % 4)
		task_switch();
}

void pit_program(s32int timer, s32int mode, s32int hz)
{
	outportb(0x43, (u8int)(0x0C | (mode << 1) | (timer << 6)));   
	s32int divisor = 1193180 / hz;
	u8int port;
	switch(timer)
	{
		case 0:
			port = 0x40;
		break;
		case 1:
			port = 0x41;
		break;
		case 2:
			port = 0x42;
		break;
		default:
			port = 0x00;
		break;
	}
	if(port)
	{
   	outportb(port, (u8int)(divisor & 0x00FF));// low byte
		outportb(port, (u8int)(divisor >> 8));    // high byte
	}
}

void pit_wait(u32int milliseconds)
{
	if(milliseconds < 10) milliseconds = 10;
   volatile u32int maxticks = pit_ticks + (milliseconds / 10);
	do { __asm__ __volatile__("hlt"); } while(pit_ticks < maxticks);
}

void init_pit(void)
{
#ifdef FLUIDIUM_DEBUG
	write_string("Pit: Init\n");
#endif

   irq_install_handler(0, pit_handler);
	pit_program(0, 3, pit_hertz);

	pit_initalized = 1;
}
